package com.xzan.medusa.common.util.http;

import com.google.gson.Gson;
import org.apache.http.HeaderElement;
import org.apache.http.HeaderElementIterator;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.ConnectionKeepAliveStrategy;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicHeaderElementIterator;
import org.apache.http.protocol.HTTP;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.SSLContext;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Map;

/**
 * @author alex
 * @date 16/10/11
 */
public class HttpsClientUtils {

    private static final Logger LOGGER = LoggerFactory.getLogger(HttpsClientUtils.class);

    private static ConnectionKeepAliveStrategy collectionStrategy = new ConnectionKeepAliveStrategy() {
        @Override
        public long getKeepAliveDuration(HttpResponse response, HttpContext context) {
            // 解析http响应中的Keep-Alive头消息
            HeaderElementIterator it = new BasicHeaderElementIterator(response.headerIterator(HTTP.CONN_KEEP_ALIVE));
            while (it.hasNext()) {
                HeaderElement header = it.nextElement();
                String param = header.getName();
                String value = header.getValue();
                // 如果制定了超时时间，则连接的存活时间为timeout的值
                if (value != null && "timeout".equalsIgnoreCase(param)) {
                    try {
                        return Long.parseLong(value) * 1000;
                    } catch (NumberFormatException e) {
                        throw new RuntimeException("Value format error.", e);
                    }
                }
            }
            // 否则默认存活30秒
            return 30 * 1000;
        }
    };

    private static HttpClient createClient() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {

        RegistryBuilder<ConnectionSocketFactory> registryBuilder = RegistryBuilder.<ConnectionSocketFactory>create();
        ConnectionSocketFactory plainConnectionSocketFactory = new PlainConnectionSocketFactory();
        registryBuilder.register("http", plainConnectionSocketFactory);

        KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
        //信任任何链接
        TrustStrategy anyTrustStrategy = new TrustStrategy() {
            @Override
            public boolean isTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
                return true;
            }
        };

        SSLContext sslContext = SSLContexts.custom().useTLS().loadTrustMaterial(trustStore, anyTrustStrategy).build();
        LayeredConnectionSocketFactory sslSF = new SSLConnectionSocketFactory(sslContext, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
        registryBuilder.register("https", sslSF);

        Registry<ConnectionSocketFactory> registry = registryBuilder.build();
        PoolingHttpClientConnectionManager clientConnectionManager = new PoolingHttpClientConnectionManager(registry);
        clientConnectionManager.setMaxTotal(2);
        clientConnectionManager.setDefaultMaxPerRoute(20);

        return HttpClientBuilder.create().setConnectionManager(clientConnectionManager).build();
    }


    public static String get(String url) {

        try {
            HttpGet httpGet = new HttpGet(url);
            HttpClient client = createClient();

            RequestConfig requestConfig = RequestConfig.custom().
                    setSocketTimeout(2000).setConnectTimeout(2000).build();
            httpGet.setConfig(requestConfig);

            HttpResponse response = client.execute(httpGet);

            if (response.getStatusLine().getStatusCode() != 200) {

                LOGGER.error("request url failed, http code=" + response.getStatusLine().getStatusCode()
                        + ", url=" + url);

                throw new Error("request url failed, http code=" + response.getStatusLine().getStatusCode()
                        + ", url=" + url);
            }

            HttpEntity entity = response.getEntity();
            String resultStr = EntityUtils.toString(entity, "utf-8");

          return resultStr;

        } catch (Exception ex) {
            throw new Error(ex);
        }

    }

    public static Map post(String url, String contentType, Object data) {
        try {
            HttpPost httpPost = new HttpPost(url);
            HttpClient client = createClient();

            RequestConfig requestConfig = RequestConfig.custom().
                    setSocketTimeout(2000).setConnectTimeout(2000).build();
            httpPost.setConfig(requestConfig);
            httpPost.addHeader("Content-Type", contentType);

            Gson gson = new Gson();

            StringEntity requestEntity = new StringEntity(gson.toJson(data), "utf-8");

            httpPost.setEntity(requestEntity);

            HttpResponse response = client.execute(httpPost);

            if (response.getStatusLine().getStatusCode() != 200) {

                LOGGER.error("request url failed, http code=" + response.getStatusLine().getStatusCode()
                        + ", url=" + url);

                throw new Error("request url failed, http code=" + response.getStatusLine().getStatusCode()
                        + ", url=" + url);
            }

            HttpEntity entity = response.getEntity();
            String resultStr = EntityUtils.toString(entity, "utf-8");

            return gson.fromJson(resultStr, HashMap.class);

        } catch (Exception ex) {
            throw new Error(ex);
        }
    }
    public static void main(String[] args){
      String map= HttpsClientUtils.get("http://hq.sinajs.cn/list=sz002299");
       System.out.println(map);
    }
}
